package system

import (
	"gitee.com/sansaniot/ssiot-core/facade/env"
	"gitee.com/sansaniot/ssiot-core/facade/runtime"
	"gitee.com/sansaniot/ssiot-core/logger"

	"ssdevice/common/constant"
	"ssdevice/common/database"
	"ssdevice/common/dto"
	"ssdevice/common/enums"
	mq "ssdevice/common/middleware/mqtt"
	"ssdevice/common/utils"
	"ssdevice/internal/data/action"
	"ssdevice/internal/data/partition"
	"ssdevice/internal/data/thread"
	"ssdevice/internal/device/models"
	"ssdevice/internal/device/models/command"
	"ssdevice/internal/device/models/query"
	"ssdevice/internal/device/service"
	"ssdevice/internal/rule/task"
)

func InitSystemBiz() {
	// 数据初始
	initDb()
	// 注册业务类
	initRegistryPartition()
	// 缓存初始化
	initSystemCache()
	// 启动数据线程
	initDataThread()
	// 启动mqtt客户端
	initMqttClient()
	// 规则引擎任务
	task.Start()
}

func initRegistryPartition() {
	// 获取db
	db := runtime.Runtime.GetDbByKey("db")
	if db == nil {
		return
	}
	// 登录
	loginAction := &action.Login{Orm: db}
	partition.Registry(enums.Login.Get().Name, loginAction)
	loginAction.Run("LoginThread")
	// 登出
	partition.Registry(enums.Logout.Get().Name, &action.Logout{Orm: db})
	// 属性
	partition.Registry(enums.Props.Get().Name, &action.Props{Orm: db})
	partition.Registry(enums.Sensor.Get().Name, &action.Sensor{Orm: db})
	// 配置
	configAction := &action.Config{Orm: db}
	partition.Registry(enums.Config.Get().Name, configAction)
	configAction.Run("ConfigThread")
}

func initDataThread() {
	// 历史数据
	thread.DevHisDataThread{}.Run("DevHisDataThread")
	// 变量表数据
	thread.DevVarDataThread{}.Run("DevVarDataThread")
	// 实时sensor
	thread.DevSensorDataThread{}.Run("DevSensorDataThread")
}

func initMqttClient() {
	mq.MqttClient = mq.NewClient()
	// 固定订阅主题
	mq.MqttClient.InitSubscribe("/iot/"+constant.TopicPlaceholder+"/+/login", mq.TopicHandler)
	mq.MqttClient.InitSubscribe("/iot/"+constant.TopicPlaceholder+"/+/logout", mq.TopicHandler)
	mq.MqttClient.InitSubscribe("/iot/"+constant.TopicPlaceholder+"/+/props", mq.TopicHandler)
	mq.MqttClient.InitSubscribe("/iot/"+constant.TopicPlaceholder+"/+/sensor", mq.TopicHandler)
	mq.MqttClient.InitSubscribe("/iot/"+constant.TopicPlaceholder+"/+/config/#", mq.TopicHandler)
	mq.MqttClient.InitSubscribe("/iot/"+constant.TopicPlaceholder+"/+/ota/#", mq.TopicHandler)
	if _, err := mq.MqttClient.CreateClient(); err != nil {
		logger.Error("mqtt连接失败" + err.Error())
	}
}

func initSystemCache() {
	// 设备缓存初始与清理
	devCache()
	// sensor本地缓存
	sensorCache()

	// 清理redis待响应消息队列
	_ = env.Cache.Del(constant.DeviceLoginCacheQueue)

	// 消费并发数
	var parallel = env.ConfigOperator.GetInt("service.device.parallel")
	if parallel > 0 {
		constant.DataRoutineChild = parallel
	}
}

func devCache() {
	if env.Db == nil {
		return
	}
	// 查所有设备
	devModel := &models.SysDev{}
	devModel.Orm = env.Db
	req := query.SysDevQuery{}
	req.UserId = "1"
	err, result := devModel.FindDeviceList(&req)
	if err != nil {
		logger.Error(err)
		return
	}
	delCaches, _ := env.Cache.HashGetAll(constant.DeviceEasyCache)
	devList := result.([]models.SysDev)
	cacheMap := map[string]interface{}{}
	cacheMap2 := map[string]interface{}{}
	for _, v := range devList {
		m := map[string]interface{}{
			"type":         v.Type,
			"name":         v.Name,
			"productModel": v.ProductModel,
			"gateway":      v.GatewaySn,
		}
		cacheMap[v.Sn] = string(utils.MapToBytes(m))
		cacheMap2[v.Sn] = v.DeptId
		delete(delCaches, v.Sn)
	}
	// 设备缓存与清理
	_ = env.Cache.HashSet(constant.DeviceEasyCache, cacheMap)
	_ = env.Cache.HashSet(constant.DeviceDeptCache, cacheMap2)
	for sn := range delCaches {
		_ = env.Cache.HashDel(constant.DeviceEasyCache, sn)
		_ = env.Cache.HashDel(constant.DeviceDeptCache, sn)
	}
}

func sensorCache() {
	if env.Db == nil {
		return
	}
	// 查所有设备
	sensorModel := &models.SysDevSensor{}
	sensorModel.Orm = env.Db
	sensorList := make([]models.SysDevSensor, 0)
	if err := sensorModel.FindList(&sensorList); err != nil {
		logger.Error(err)
		return
	}
	for _, sensor := range sensorList {
		constant.SensorCache.Store(sensor.DevSn, string(sensor.Data))
	}
}

func initDb() {
	// 默认产品初始确认
	pdmodel := &models.SysDevProduct{}
	pdmodel.Orm = env.Db
	_ = pdmodel.FindOne(pdmodel, dto.MakeCondition(query.SysProductQuery{ProductModel: constant.DefaultProductCode}))
	if len(pdmodel.Id) == 0 {
		pdservice := &service.Product{}
		pdservice.Orm = env.Db
		pdservice.SetAllModel()
		if err, _ := pdservice.AddProduct(&command.ProductInsertReq{
			Name:         "默认产品",
			DeviceType:   enums.DevTypeOfDevice,
			ProductModel: constant.DefaultProductCode,
			DeptId:       constant.PublicGroupId,
			Photo:        "",
			Description:  "",
			View:         nil,
			DevSchema:    &models.SysDevSchema{Schema: []byte(constant.DevDefaultSchemaTemplate)},
			DevConfig:    &models.SysDevConfig{Data: []byte(constant.DevDefaultConfigTemplate)},
		}); err != nil {
			logger.Errorf("初始化默认产品异常,%v", err)
		}
	}
	// 启动历史数据分区表
	var partitionFlag = env.ConfigOperator.GetBool("service.device.partition")
	if partitionFlag {
		database.PartitionTb(env.Db, models.SysHistorySensor{}.TableName())
	}
}
